package com.googlecode.player.controller.mediators
{
	import com.googlecode.data.materials.FileAssetMaterialVO;
	import com.googlecode.data.materials.MaterialVO;
	import com.googlecode.data.materials.MovieMaterialVO;
	import com.googlecode.data.objects3d.CubeVO;
	import com.googlecode.data.objects3d.MaterialsListObject3DVO;
	import com.googlecode.data.objects3d.Object3DVO;
	import com.googlecode.data.objects3d.SingleMaterialObject3DVO;
	import com.googlecode.data.objects3d.SphereVO;
	import com.googlecode.player.model.Animator3DPlayerProxy;
	import com.googlecode.player.view.specialmaterials.ControlledMovieMaterial;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	
	import mx.controls.SWFLoader;
	
	import org.papervision3d.materials.MovieMaterial;
	import org.puremvc.as3.multicore.interfaces.IProxy;
	import org.puremvc.as3.multicore.patterns.mediator.Mediator;

	public class SWFLoaderMediator extends Mediator
	{
		/**
		 * Name prefix used to create dynamic mediator names.
		 * Names will be appended by the INSTANCE_COUNT to create a unique mediator name. 
		 */
		public static const NAME_PREFIX:String = "SWFLoaderMediator_";
		
		/**
		 * Counter indicating how many instances of this class have been created. 
		 */		
		protected static var INSTANCE_COUNT:uint = 0;
		
		/**
		 * SWFLoader required temporarily to load swfs. 
		 */
		private var _loader:SWFLoader = new SWFLoader();
		
		/**
		 * Reference to the object3D. 
		 */
		private var _object3D:*;
		
		/**
		 * Reference to the material. 
		 */
		private var _mat:MaterialVO;
		
		/**
		 * Constructor. 
		 * @param object3D
		 * 
		 */
		public function SWFLoaderMediator(object3D:*)
		{
			super(NAME_PREFIX + INSTANCE_COUNT);
			
			_object3D = object3D;
			
			// update instance count so we obtain a unique name for each Mediator instance
			INSTANCE_COUNT++;
		}
		
		/**
		 * Links in with PureMVC framework. 
		 * 
		 */
		override public function onRegister():void
		{	
			// we need to get the material in question from the object3D
			
			if(_object3D is SingleMaterialObject3DVO)
			{
				_mat = (_object3D as SingleMaterialObject3DVO).material as MovieMaterialVO;
			}
			
			if(_object3D is MaterialsListObject3DVO)
			{
				_mat = (_object3D as MaterialsListObject3DVO).materialsList[(_object3D as MaterialsListObject3DVO).selectedFace];
			}
			
			// now add  event listeners to loader and load the swf
			_loader.addEventListener(Event.COMPLETE, onSWFComplete);
			_loader.addEventListener(IOErrorEvent.IO_ERROR, onError);
			_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			_loader.load((_mat as FileAssetMaterialVO).filePath); 
		}
		
		/**
		 * Called by the PureMVC framework when the mediator is removed. 
		 * 
		 */
		override public function onRemove():void
		{
			_loader.removeEventListener(Event.COMPLETE, onSWFComplete);
			_loader.removeEventListener(IOErrorEvent.IO_ERROR, onError);
			_loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			
			// not sure if this is necessary?
			_loader = null;
		}
		
		/**
		 * Handles the loading of a SWF. 
		 * @param evt
		 * 
		 */
		protected function onSWFComplete(evt:Event):void
		{	
			var swf:DisplayObject = (evt.target as SWFLoader).content;
						
			var matVO:MovieMaterialVO = new MovieMaterialVO();
			//var mat:MovieMaterial = new MovieMaterial(swf, matVO.transparent, matVO.animated);
			var mat:*;

			
			if((_mat as MovieMaterialVO).showControls)
			{
				mat = new ControlledMovieMaterial(swf, (_mat as MovieMaterialVO).transparent);
			}else
			{
				mat = new MovieMaterial(swf, (_mat as MovieMaterialVO).transparent, matVO.animated);
			}

			//var mat:ControlledMovieMaterial = new ControlledMovieMaterial(swf, matVO.transparent, matVO.animated);
			mat.smooth = (_mat as MovieMaterialVO).smooth;
			
			// set the material on the object3D in the scene
			if(_object3D is SingleMaterialObject3DVO)
			{
				//mat = (_object3D as PlaneVO).material as MovieMaterialVO;
				settings.scene.getChildByName((_object3D as SingleMaterialObject3DVO).name).material = mat;
			}
			
			if(_object3D is MaterialsListObject3DVO)
			{
				//mat = (_object3D as CubeVO).materialsList[(_object3D as CubeVO).selectedFace] as MovieMaterialVO;
				settings.scene.getChildByName((_object3D as MaterialsListObject3DVO).name).replaceMaterialByName(mat, (_object3D as MaterialsListObject3DVO).selectedFace);
			}
			
			//sendNotification(Notifications.OBJECT3D_MATERIAL_CHANGED);
			//settings.calculateTweens((_object3D as Object3DVO).name);
			// we can't guarantee that the Mediator instance was registered
			if(facade)
			{
				facade.removeMediator(getMediatorName());
			}
				
		}
		
		/**
		 * Handles errors resulting from the loading of a SWF. 
		 * @param error
		 * 
		 */
		protected function onError(error:IOErrorEvent):void
		{
			trace(error.text);
			
			// we can't guarantee that the Mediator instance was registered
			if(facade)
			{
				facade.removeMediator(getMediatorName());
			}
		}
		
		/**
		 * Handles security errors. 
		 * @param error
		 * 
		 */
		protected function onSecurityError(error:SecurityErrorEvent):void
		{	
			trace(error.text);
			
			// we can't guarantee that the Mediator instance was registered
			if(facade)
			{
				facade.removeMediator(getMediatorName());
			}	
		}
		
		/**
		 * Returns typed reference to model. 
		 * @return 
		 * 
		 */
		protected function get settings():Animator3DPlayerProxy
		{
			var proxy:IProxy = facade.retrieveProxy(Animator3DPlayerProxy.NAME);
			
			return proxy as Animator3DPlayerProxy;
		}
	}
}